from django.http import Http404
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.views import APIView

from exercise.models import Question, QuestionGroup
from padmin.permissions import IsAdminPermission
from padmin.serializer import ProjUserGroupPostSerializer, ProjUserGroupPutSerializer
from user.models import ProjUserGroup, ProjUser


# Create your views here.
class PadminUserGroupPostEdit(APIView):
    permission_classes = [IsAdminPermission, ]

    def post(self, request):
        """
        用于管理员创建群组的api

        需要上传的数据格式如下：
        ```json
        "data": {
            "name": "这是群组名",
            "description": "这是群组描述",
            "members": [ // 这是需要加入群组的成员们的id
                1,
                2,
                3,
            ]
        }
        ```

        创建成功则返回`200`，否则返回`400`
        """
        creator_id = ProjUser.objects.get(username=request.user.username).id  # 创建者的用户id
        user_list = request.data['members']
        if creator_id not in user_list:
            user_list.append(creator_id)
            request.data['members'] = user_list
        s = ProjUserGroupPostSerializer(data=request.data)
        if s.is_valid():
            s.validated_data['creator'] = request.user
            s.save()
            return Response(s.data, status=status.HTTP_200_OK)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)

    def put(self, request, group_id):
        """
        用于管理员更新指定群组信息的api

        url中需要在最后提供`group_id`参数来确定需要更新的组id

        允许更新字段为`name`和`description`且允许部分更新

        ```json
        "data":{
            "name": "newName",
            "description": "这是一个新的群组介绍"
        } // (可以只上传部分信息)
        ```
        更新成功则返回200，失败则返回400
        """
        try:
            group = ProjUserGroup.objects.get(id=group_id)
        except ProjUserGroup.DoesNotExist:
            return Response({'message': '该群组不存在'}, status=status.HTTP_404_NOT_FOUND)
        s = ProjUserGroupPutSerializer(instance=group, data=request.data, partial=True)
        if s.is_valid():
            s.save()
            return Response(s.data, status=status.HTTP_200_OK)
        return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, group_id):
        """
        用于管理员删除指定群组的api
        url中需要在最后提供`group_id`参数来确定需要删除的组id
        删除成功则返回`204`，失败则返回`404`
        """
        try:
            group = ProjUserGroup.objects.get(id=group_id)
        except ProjUserGroup.DoesNotExist:
            return Response({'message': '该群组不存在'}, status=status.HTTP_404_NOT_FOUND)
        ProjUserGroup.delete(group)
        return Response({'message': '解散成功'}, status=status.HTTP_204_NO_CONTENT)


class PadminUserGroupMemberManage(APIView):
    """
    用于管理员向群组内批量添加/删除组员的api，添加和删除的请求数据格式要求一致
    ```json
    "data":{
        "group_id": 114, // 希望操作的群组id
        "user_ids": [ // 希望加入/删除的用户id
            5,
            1,
            4,
        ]
    }
    ```
    """
    permission_classes = [IsAdminPermission, ]

    def get_group(self, group_id):
        try:
            return ProjUserGroup.objects.get(id=group_id)
        except ProjUserGroup.DoesNotExist:
            raise Http404

    def put(self, request):
        group_id = request.data.get('group_id', None)
        user_ids = request.data.get('user_ids', None)
        try:
            group_id = int(group_id)
            if not isinstance(user_ids, list):
                raise ValueError("不是列表")
        except ValueError as e:
            return Response({'message': '请确保组号是非负整数，用户id列表为非负整数列表'}, status=status.HTTP_400_BAD_REQUEST)
        group = self.get_group(group_id)
        ne_list = []
        wa_list = []
        ill_list = []
        for user_id in user_ids:
            try:
                if not isinstance(user_id, int):
                    raise TypeError  # 非法参数
                user = ProjUser.objects.get(id=user_id)
                if user.group_list.filter(id=group_id).exists():
                    raise ValueError("重复添加")
                group.members.add(user)
            except ProjUser.DoesNotExist:
                ne_list.append(user_id)  # 不存在的id
            except ValueError:
                wa_list.append(user_id)  # 组中已有此人
            except TypeError:
                ill_list.append(user_id)
        return Response({'不存在的用户': ne_list, '重复添加的用户': wa_list,  '列表中非法参数': ill_list}, status=status.HTTP_200_OK)

    def delete(self, request):
        group_id = request.data.get('group_id', None)
        user_ids = request.data.get('user_ids', None)
        try:
            group_id = int(group_id)
            if not isinstance(user_ids, list):
                raise ValueError("不是列表")
        except ValueError as e:
            return Response({'message': '请确保组号是非负整数，用户id列表为非负整数列表'}, status=status.HTTP_400_BAD_REQUEST)
        group = self.get_group(group_id)
        ne_list = []
        wa_list = []
        ill_list = []
        for user_id in user_ids:
            if user_id == group.creator.id:
                continue
            try:
                if not isinstance(user_id, int):
                    raise TypeError  # 非法参数
                user = ProjUser.objects.get(id=user_id)
                if not user.group_list.filter(id=group_id).exists():
                    raise ValueError
                group.members.remove(user)
            except ProjUser.DoesNotExist:
                ne_list.append(user_id)  # 不存在的id
            except ValueError:
                wa_list.append(user_id)  # 组中无此人
            except TypeError:
                ill_list.append(user_id)
        return Response({'不存在的用户': ne_list, '组中不存在的用户': wa_list, '列表中非法参数': ill_list}, status=status.HTTP_200_OK)


@api_view(['DELETE'])
@permission_classes([IsAdminPermission, ])
def ban_question(request, question_id):
    """
    通过url传入指定的问题id，并将其封禁
    """
    try:
        question = Question.objects.get(id=question_id)
    except Question.DoesNotExist:
        return Response({'message': '问题不存在'}, status=status.HTTP_404_NOT_FOUND)
    question.is_banned = True
    return Response(status=status.HTTP_200_OK)


@api_view(['DELETE'])
@permission_classes([IsAdminPermission, ])
def ban_question_group(request, group_id):
    """
    通过url传入指定的问题组id，并将其封禁
    """
    try:
        group = QuestionGroup.objects.get(id=group_id)
    except QuestionGroup.DoesNotExist:
        return Response({'message': '问题组不存在'}, status=status.HTTP_404_NOT_FOUND)
    group.is_banned = True
    return Response(status=status.HTTP_200_OK)
